<?php
namespace Miniprogram\Controller;
use Think\Controller;
class WxController extends Controller {

    public $appid='wx3423e3dcff141768';
    public $secret='ee98497470e58ff60b68301ced8ba688';
    public $accesstoken='';
    public $mch_id='1602363406';
    public $mch_key='ee98497470e58ff60b68301ced8ba611';
    public $mck_key_sanxbox='ee98497470e58ff60b68301ced8ba611';
    public $ip='218.60.0.215';
    protected $is_test=false;

    protected $m;
    protected $lang;
    protected $config;

    public function _initialize(){
        //$this->accesstoken=$this->GetAccessToken();
        $this->m=D('member');
        $this->lang=(I('get.lang'))?I('get.lang'):'cn';
        $this->config=C('lang_'.$this->lang);
        $this->config['login_first'];
        if($this->is_test)
            $this->mch_key=$this->mck_key_sanxbox;
    }
    /*获取token*/
    protected function GetAccessToken(){
        $token = json_decode(require(__PHYSICS__.'/Application/Miniprogram/Conf/accesstoken.php'));
        if(!$token->access_token||($token->expires_in+$token->addtime<time())){
            return $this->SetAccessToken();
        }else
            return $token->access_token;
    }
    /*设置token*/
    protected function SetAccessToken(){
        $token=json_decode(get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$this->appid.'&secret='.$this->secret));
        $token->addtime=time();
        $acces=json_encode($token);
        $data="<?php return '$acces'; ?>";
        file_put_contents(__PHYSICS__.'/Application/Miniprogram/Conf/accesstoken.php',$data);
        return $token->access_token;
    }
    /*微信小程序登录流程*/
    protected function WxLogin($js_code){
        $res=get('https://api.weixin.qq.com/sns/jscode2session?appid='.$this->appid.'&secret='.$this->secret.'&js_code='.$js_code.'&grant_type=authorization_code');
//        $res=json_encode(array(
//            'openid'=>'oaJyB4lHATq6Ti7d6fWUsQv-zw_o',
//            'session_key'=>'QWERTYUIOP12456'
//        ));
        return $res;
    }
    /*微信小程序用户登录*/
    public function login(){
        $code = I('post.code','','string');
        if(empty($code))
            error($this->config['parr_err']);
        $openid=json_decode($this->WxLogin($code));
        if($openid->errcode)
            error_sys($this->config['wx_login_fail']);
        $userInfo=$this->m->where(array('openid'=>$openid->openid))->find();
        if(!empty($userInfo)){
            if(I('post.nickName')&&I('post.avatarUrl')) {
                $this->m->where(array('openid' => $openid->openid))->save(array(
                    'nickname' => I('post.nickName'),
                    'avatar' => I('post.avatarUrl')
                ));
            }
        }else{
            $res = $this->m->add(array(
                'nickname' => I('post.nickName'),
                'openid' =>$openid->openid,
                'avatar' => I('post.avatarUrl')
            ));
            $userInfo['id'] = $res;
        }
        success(array('token'=>$this->m->login($userInfo['id'],$userInfo['username'])),$this->config['success']);
    }
    /*微信小程序用户注册*/
    public function register(){
        $data=I('post.');
        if(!$data['username']||!$data['pwd']||!$data['email']||!$data['valid'])
            error($this->config['parr_err']);
        if($data['valid']!=substr(md5($data['email'].$data['email']),2,6))
            error($this->config['email_valid_err']);
        if($this->m->where(['username'=>$data['username']])->getField('id'))
            error($this->config['user_existed']);
        if($memberInfo=$this->m->where(array('email'=>$data['email']))->find())
            error($this->config['mail_occupied']);
        $res=$this->m->add(array(
            'username'=>$data['username'],
            'pwd'=>md5($data['pwd']),
            'openid'=>$data['openid'],
            'email'=>$data['email']
        ));
        if($res){
            success([
                'token'=>$this->m->login($res,$data['username']),
            ],$this->config['success']);
        }
        else{
            error($this->config['error']);
        }
    }
    /*微信小程序用户绑定账号密码*/
    public function bind(){
        $data=I('post.');
        if(!$data['username']||!$data['pwd']||!$data['openid'])
            error($this->config['parr_err']);
        if(!$memberInfo=$this->m->where([
            'username'=>$data['username'],
            'pwd'=>md5($data['pwd'])
        ])->find())
            error($this->config['user_not_exist']);
        if($memberInfo['openid'])
            error($this->config['user_bind_already']);
        $res=$this->m->save(array(
            'id'=>$memberInfo['id'],
            'openid'=>$data['openid']
        ));
        if($res){
            success([
                'token'=>$this->m->login($memberInfo['id'],$data['username']),
            ],$this->config['success']);
        }
        else{
            error($this->config['error']);
        }
    }
    /*微信小程序支付*/
    public function pay($order_no,$openid,$price){
        if($this->is_test)
            $url='https://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder';
        else
            $url='https://api.mch.weixin.qq.com/pay/unifiedorder';
        $data=[
            'appid'=>$this->appid,
            'mch_id'=>$this->mch_id,
            'nonce_str'=>md5($order_no),
            'body'=>'北郡搬家订单',
            'out_trade_no'=>$order_no,
            'total_fee'=>$price*100,
            // 'total_fee'=>1,
            'spbill_create_ip'=>$this->ip,
            'notify_url'=>'https://bj.d1.pg024.com/Wx/payNotify',
            'trade_type'=>'JSAPI',
            'openid'=>$openid
        ];
        // ll($data);
        $data['sign']=$this->getSign($data);
        $data=xml_encode($data,'xml');
        $res=xmltoarr(post($url,$data));
        // ll($res);die;
        if($res['return_code']!='SUCCESS')
            error($this->config['error']);
        if($res['err_code'])
            error($res['err_code_des']);
        $data=[
            'appId'=>$this->appid,
            'timeStamp'=>time().'',
            'nonceStr'=>$res['nonce_str'],
            'package'=>'prepay_id='.$res['prepay_id'],
            'signType'=>'MD5'
        ];
        $data['paySign']=$this->getSign($data);
        return ($data);
    }
    /*微信支付生成签名*/
    private function getSign($params) {
        ksort($params);        //将参数数组按照参数名ASCII码从小到大排序
        foreach ($params as $key => $item) {
            if (!empty($item)) {         //剔除参数值为空的参数
                $newArr[] = $key.'='.$item;     // 整合新的参数数组
            }
        }
        $stringA = implode("&", $newArr);         //使用 & 符号连接参数
        $stringSignTemp = $stringA."&key=".$this->mch_key;        //拼接key
        // key是在商户平台API安全里自己设置的
        $stringSignTemp = MD5($stringSignTemp);       //将字符串进行MD5加密
        $sign = strtoupper($stringSignTemp);      //将所有字符转换为大写
        return $sign;
    }
    /*支付回调接口*/
    public function payNotify(){
        // echo 111;die;
        //接收微信返回的数据数据,返回的xml格式
        $xmlData = file_get_contents('php://input');
        //将xml格式转换为数组
        $data = xmltoarr($xmlData);
        //用日志记录检查数据是否接受成功，验证成功一次之后，可删除。
        $file = fopen('./log.txt', 'a+');
        fwrite($file,var_export($data,true));
        //为了防止假数据，验证签名是否和返回的一样。
        //记录一下，返回回来的签名，生成签名的时候，必须剔除sign字段。
        $sign = $data['sign'];
        unset($data['sign']);
        if($sign == $this->getSign($data)){
            //签名验证成功后，判断返回微信返回的
            if ($data['result_code'] == 'SUCCESS') {
                //根据返回的订单号做业务逻辑
                if(strpos($data['out_trade_no'],'BJ') !== false){ 
                    //预付款
                    $arr = array(
                        'status' => 1,
                        'paytime'=>date('Y-m-d H:i:s'),
                        'pay_from'=>'wx'
                    );
                    $re = M('order')->where(['order_no'=>$data['out_trade_no']])->save($arr);
                    $valuation_id = M('order')->where(['order_no'=>$data['out_trade_no']])->getField('valuation_id');//意向记录id
                    if(!empty($valuation_id)){
                		M('order_valuation')->where(['id'=>$valuation_id])->delete();//订单已支付，删除意向记录
                    }
                }else{
                    $arr = array(
                        'status' => 4,
                    );
                    $re = M('order')->where(['order_no_small'=>$data['out_trade_no']])->save($arr);
                }
                //处理完成之后，告诉微信成功结果！
                if($re){
                    echo xml_encode([
                        'return_code'=>'SUCCESS',
                        'return_msg'=>'OK'
                    ]);
                    exit();
                }
            }
            //支付失败，输出错误信息
            else{
                $file = fopen('./log.txt', 'a+');
                fwrite($file,"错误信息：".$data['return_msg'].date("Y-m-d H:i:s"),time()."\r\n");
            }
        }
        else{
            $file = fopen('./log.txt', 'a+');
            fwrite($file,"错误信息：签名验证失败".date("Y-m-d H:i:s"),time()."\r\n");
        }

    }
    /*获取沙盒支付签名*/
    public function getSandBoxKey(){
        $url='https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey';
        $data=[
            'mch_id'=>$this->mch_id,
            'nonce_str'=>md5(time()),
        ];
        $data['sign']=$this->getSign($data);
        $res=xmltoarr(post($url,xml_encode($data,'xml')));
        success($res);
    }
    /*退款*/
    public function refund($data){
        // echo 1;die;
        error_reporting(E_ALL);
        if($this->is_test)
            $url='https://api.mch.weixin.qq.com/sandboxnew/secapi/pay/refund';
        else
            $url='https://api.mch.weixin.qq.com/secapi/pay/refund';
        $data=[
            'appid'=>$this->appid,
            'mch_id'=>$this->mch_id,
            'nonce_str'=>md5($data['refund_no']),
            'out_trade_no'=>$data['order_no'],
            'out_refund_no'=>$data['refund_no'],
            'total_fee'=>$data['total_fee'],
            'refund_fee'=>$data['refund_fee'],
        ];
        // ll($data);die;
        $data['sign']=$this->getSign($data);
        $res=post($url,xml_encode($data,'xml'),[
            'cert'=>__PHYSICS__.'/Application/Common/Cert/apiclient_cert.pem',
            'key'=>__PHYSICS__.'/Application/Common/Cert/apiclient_key.pem',
        ]);
        return xmltoarr($res);
    }

}